#include "MCP23017.h"
#include "ohos_types.h"
#include <stdio.h>
#include "cmsis_os2.h"
#include "iot_gpio.h"
#include "iot_i2c.h"

int MCP23017_INIT(uint8 deviceAddr,uint8 intab,uint8 hwa,uint8 o){
    uint8 state = 0x2E;
    int res;

    if(intab==INTA_INTB_CONJUNCTION){
		state |= 0x40;
	}
	if(hwa==HWA_DIS){
		state &= (~0x08);
	}
	if(o==INT_PUSHPULL_HIGH){
		state &= (~0x04);
		state |= 0x02;
	}
	if(o==INT_PUSHPULL_LOW){
		state &= (~0x04);
		state &= (~0x02);
	}

    res = I2C_Write_Byte_MCP23017(deviceAddr,MCP23017_IOCON,state);

    return res;
}
 
int MCP23017_IO_DIR(uint8 deviceAddr,uint8 port,uint8 pin,uint8 dir){
    uint8 portState = 0;
    int res;
    res = I2C_Read_Byte_MCP23017(deviceAddr,MCP23017_IODIR+port,&portState);

	if(res == 0){
		return res;
	}

	if(dir==INPUT){
		portState |= pin;
	}else{
		portState &= (~pin);
	}

	res = I2C_Write_Byte_MCP23017(deviceAddr,MCP23017_IODIR+port,portState);
	
	return res;
}

int MCP23017_IO_PU(uint8 deviceAddr,uint8 port,uint8 pin,uint8 pu){
    uint8 portState = 0;
    int res;
    res = I2C_Read_Byte_MCP23017(deviceAddr,MCP23017_GPPU+port,&portState);
	if(res == 0){
		return res;
	}

	if(pu==ENABLE){
		portState |= pin;
	}else{
		portState &= (~pin);
	}
	res = I2C_Write_Byte_MCP23017(deviceAddr,MCP23017_GPPU+port,portState);
	
	return res;
}
  
int MCP23017_IO_POLARITY(uint8 deviceAddr,uint8 port,uint8 pin,uint8 polarity){
    uint8 portState = 0;
	int res;
	
	res = I2C_Read_Byte_MCP23017(deviceAddr,MCP23017_IPOL+port,&portState);

	if(res == 0){
		return res;
	}

	if(polarity==POLARITY_REVERSE){
		portState |= pin;
	}else{
		portState &= (~pin);
	}

	res = I2C_Write_Byte_MCP23017(deviceAddr,MCP23017_IPOL+port,portState);
	
	return res;
}
  
int MCP23017_IO_INT(uint8 deviceAddr,uint8 port,uint8 pin,uint8 intKind){
    uint8 portState_GPINTEN = 0;
	uint8 portState_DEFVAL = 0;
	uint8 portState_INTCON = 0;
	int res;
	
	res = I2C_Read_Byte_MCP23017(deviceAddr,MCP23017_GPINTEN+port,&portState_GPINTEN);

	if(res == 0){
		return res;
	}
	res = I2C_Read_Byte_MCP23017(deviceAddr,MCP23017_DEFVAL+port,&portState_DEFVAL);

	if(res == 0){
		return res;
	}
	res = I2C_Read_Byte_MCP23017(deviceAddr,MCP23017_INTCON+port,&portState_INTCON);

	if(res == 0){
		return res;
	}

	if(intKind==DIS_INTERRUPT){
		portState_GPINTEN &= (~pin);		
	}

	if(intKind==CHANGE_INTERRUPT){
		portState_GPINTEN |= pin;
		portState_INTCON &= (~pin);		
	}

	if(intKind==HIGHLEVEL_INTERRUPT){
		portState_GPINTEN |= pin;
		portState_INTCON |= pin;
		portState_DEFVAL &= (~pin);		
	}

	if(intKind==LOWLEVEL_INTERRUPT){
		portState_GPINTEN |= pin;
		portState_INTCON |= pin;
		portState_DEFVAL |=pin;		
	}

	res = I2C_Write_Byte_MCP23017(deviceAddr,MCP23017_GPINTEN+port,portState_GPINTEN);
	
	if(res == 0){
		return res;
	}
	res = I2C_Write_Byte_MCP23017(deviceAddr,MCP23017_INTCON+port,portState_INTCON);
	
	if(res == 0){
		return res;
	}
	res = I2C_Write_Byte_MCP23017(deviceAddr,MCP23017_DEFVAL+port,portState_DEFVAL);
	
	if(res == 0){
		return res;
	}
	
	return res;
}

uint8 MCP23017_READ_INTF(uint8 deviceAddr,uint8 port){
    uint8 portState = 0;
	int res;
	
	res = I2C_Read_Byte_MCP23017(deviceAddr,MCP23017_INTF+port,&portState);

	//如果出错则返回0
	if(res == 0){
		return 0;
	}else{
		return portState;
	}
}
 
uint8 MCP23017_READ_INTCAP(uint8 deviceAddr,uint8 port){
    uint8 portState = 0;
	int res;
	
	res = I2C_Read_Byte_MCP23017(deviceAddr,MCP23017_INTCAP+port,&portState);

	//如果出错则返回0
	if(res == 0){
		return 0;
	}else{
		return portState;
	}
}
 
uint8 MCP23017_READ_GPIO(uint8 deviceAddr,uint8 port){
    uint8 portState = 0;
	int res;
	
	res = I2C_Read_Byte_MCP23017(deviceAddr,MCP23017_GPIO+port,&portState);

	if(res == 0){
		return 0;
	}else{
		return portState;
	}
}

int MCP23017_WRITE_GPIO(uint8 deviceAddr,uint8 port,uint8 val){
    int res;
	
	res = I2C_Write_Byte_MCP23017(deviceAddr,MCP23017_GPIO+port,val);

	return res;
}

int MCP23017_SET_GPIO_PIN(uint8 deviceAddr,uint8 port,uint8 pin,uint8 s){
    uint8 portState = 0;
	int res;
	
	res = I2C_Read_Byte_MCP23017(deviceAddr,MCP23017_GPIO+port,&portState);

	//如果出错则返回
	if(res == 0){
		return res;
	}

	if(s ==SET){
		portState |= pin;
	}else{
		portState &= (~pin);
	}

	//写回方向寄存器
	res = I2C_Write_Byte_MCP23017(deviceAddr,MCP23017_GPIO+port,portState);
	
	return res;
}
 
uint8 MCP23017_READ_OLAT(uint8 deviceAddr,uint8 port){
    uint8 portState = 0;
	int res;
	
	res = I2C_Read_Byte_MCP23017(deviceAddr,MCP23017_OLAT+port,&portState);

	if(res == 0){
		return 0;
	}else{
		return portState;
	}
}
 
int MCP23017_WRITE_OLAT(uint8 deviceAddr,uint8 port,uint8 val){
    int res;
	
	res = I2C_Write_Byte_MCP23017(deviceAddr,MCP23017_OLAT+port,val);

	return res;
}
 
int I2C_Read_Byte_MCP23017(uint8 deviceAddr, uint8 regAddress, uint8* recv){

    uint8_t writeBuf[1] = {0};
	writeBuf[0] = regAddress;
	IoTI2cWrite(MCP23017_I2C_IDX, (DRIVER_ID | (deviceAddr<<1) | I2C_WRITE), writeBuf, 1);

    uint8_t readBuf[1] = {0};
   	uint32_t Rresult = IoTI2cRead(MCP23017_I2C_IDX, (DRIVER_ID | (deviceAddr<<1) | I2C_READ), readBuf, 1);

    //printf("[MCP23017 READ]%d \r\n",Rresult);

    *recv = readBuf[0];

    if(Rresult == 0){
        Rresult = 1;
    }

    return Rresult;
}

int I2C_Write_Byte_MCP23017(uint8 deviceAddr, uint8 regAddress, uint8 content){

    uint8_t write_data[3] = {regAddress,content};
	uint32_t result = IoTI2cWrite(MCP23017_I2C_IDX, (DRIVER_ID | (deviceAddr<<1) | I2C_WRITE), write_data, 2);
    //printf("[MCP23017 WRITE]%d \r\n",result);

	// printf("[MCP23017 WRITE address]%02X  \r\n",(DRIVER_ID | (deviceAddr<<1) | I2C_WRITE));

    if(result == 0){
        result = 1;
    }

    return result;
}
